package com.sunyard.pcc.core.aspect;

import com.google.gson.Gson;
import com.sunyard.pcc.common.constant.ErrorCodeEnum;
import com.sunyard.pcc.common.exception.PccCommonException;
import com.sunyard.pcc.common.shiro.ShiroUtils;
import com.sunyard.pcc.common.utils.HttpUtil;
import com.sunyard.pcc.core.annotation.SysLog;
import com.sunyard.pcc.dal.mapper.ext.SysLogExtMapper;
import com.sunyard.pcc.dal.model.SysLogDO;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @Author: Hewei
 * @Description: 日志操作对应切面
 * @Date: Created in 16:41 2018/3/14
 */
@Aspect
@Component
public class SysLogAspect {

    @Autowired
    private SysLogExtMapper sysLogExtMapper;

    @Pointcut(value = "@annotation(com.sunyard.pcc.core.annotation.SysLog)")
    public void logAnnotationPointCut(){}


    /**
     * 环绕日志通知
     * @param point
     * @return
     */
    @Around(value = "logAnnotationPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable{
        long start = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //方法执行时长
        long time = System.currentTimeMillis() - start;
        saveSysLog(point, time);
        return result;
    }

    /**
     * 保存日志
     * @param point
     * @param time
     * @throws PccCommonException
     */
    private void saveSysLog(ProceedingJoinPoint point, long time) throws PccCommonException{

        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        SysLogDO sysLogDO = new SysLogDO();

        SysLog annoLog = method.getAnnotation(SysLog.class);
        if ( annoLog != null ){
            sysLogDO.setOperation(annoLog.operation());
        }

        //请求的完整方法名
        String className = point.getTarget().getClass().getName();
        String methodName = method.getName();
        sysLogDO.setMethod(className + "." + methodName + "()");

        //请求的参数
        Object[] params = point.getArgs();
        String param = new Gson().toJson(params);
        sysLogDO.setParams(param);

        //获取request和Ip
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = HttpUtil.getIPByRequest(request);
        sysLogDO.setIp(ip);

        //获取用户名
        String username = ShiroUtils.getCacheUser().getTelephone();
        sysLogDO.setUsername(username);

        sysLogDO.setTime(time);
        int i = sysLogExtMapper.insertSelective(sysLogDO);
        if (i != 1){
            throw new PccCommonException(ErrorCodeEnum.INSERT_ERROR);
        }

    }

}
